package cn.tedu.jdbc;

import cn.tedu.jdbc.utils.DbUtils;

import java.sql.*;
import java.util.Scanner;

/**
 * PreparedStatement的原理：
 * 1.先对SQL语句进行预先编译
 * 2.给SQL语句中占位符传值
 *
 * 重点注意事项：
 * 在使用预编译的数据可操作对象PreparedStatement时，需要先编写SQL语句，然后再获取PreparedStatement对象。
 * 这里编写的SQL语句中，所有的“值”位置都要都要使用占位符来代替，占位符为 ？，？占位符两边不需要加单引号和双引号
 * 每一个问号是一个值。是一个占位符。
 * 另外，特别要注意：这个占位符问号？两边不能使用单引号或双引号括起来。
 *
 * 解决SQL注入的本质是：将带有占位符的SQL语句进行预先编译，然后给占位符传值，即使用户提供的信息中含有SQL语句关键字，
 * 但是这些关键字不会参与SQL语句的编译，自然不会扭曲SQL语句的原意。
 */
public class JDBCTest11 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("欢迎使用用户管理系统，请登录！");
        System.out.println("用户名：");
        String loginName = scanner.nextLine();
        System.out.println("密码");
        String loginpwd = scanner.nextLine();

        // 定义数据库连接变量
        Connection conn = null;
        // 定义SQL执行语句变量
        Statement stmt = null;
        // 定义结果集变量
        ResultSet rs = null;
        // 定义预编译SQL语句变量
        PreparedStatement ps = null;
        // 定义登录成功标志变量，默认为false
        boolean loginSuccess = false;
        // 定义用户真实姓名变量
        String realname = null;


        try {
            conn = DbUtils.getConnection();
            //获取预编译的数据库操作对象
            /*以下是对上述代码的中文解释：
            1. `String sql = "select * from t_user where name = ? and password = ?";`
            - 定义一个 SQL 查询语句，用于从 `t_user` 表中查询用户名（`name`）和密码（password)匹配的用户信息。
            - 使用 `?` 作为参数占位符，可以防止 SQL 注入攻击，并允许后续通过 `PreparedStatement` 动态设置参数值。
            2. `ps = conn.prepareStatement(sql);`
            - 使用数据库连接对象 `conn` 创建一个 `PreparedStatement` 实例 `ps`，将上面定义的 SQL 语句进行预编译。
            - `PreparedStatement` 不仅可以提高执行效率，还支持安全地传入参数值，避免拼接 SQL 字符串带来的风险。*/
            String sql = "select * from t_user where name = ? and password = ?";
            // 准备SQL语句，用于执行查询或更新操作
            ps = conn.prepareStatement(sql);

            //给 ？ 占位符传值(用户名)
            ps.setString(1,loginName);
            //给 ？ 占位符传值(密码)
            ps.setString(2,loginpwd);
            //执行SQL语句，获取结果集
            rs = ps.executeQuery();
            if (rs.next()){
                //登陆成功
                loginSuccess = true;
                //获取真实名字
                realname = rs.getString("realname");
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            DbUtils.close(conn,ps,rs);
        }
        System.out.println(loginSuccess ? "登陆成功，欢迎" + realname : "登陆失败，您的用户名或密码错误");
    }
}